﻿using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using $ext_safeprojectname$.redismodel;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Domain.Repositories;

namespace $ext_safeprojectname$.usermodels
{

    /// <summary>
    /// 权限列表
    ///</summary>
    [TypeFilter(typeof(RoleAttribute), Arguments = new object[] { "data", "add" })]
    public class RoleInfoAppService : $ext_safeprojectname$AppService
    {

        //private readonly IRepository<RoleInfo, int> _repository;


        private readonly I$ext_safeprojectname$DbContext _dbContext;

        private readonly IAppCache _cache;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="cache"></param>
        public RoleInfoAppService(I$ext_safeprojectname$DbContext dbContext, IAppCache cache)
        {

            _dbContext = dbContext;
            _cache = cache;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="page"></param>
        /// <param name="size"></param>
        /// <param name="groupid"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<PagedResultDto<RoleInfoListDto>> GetListAsync(int page = 1, int size = 20, int groupid = 0)
        {

            var query = _dbContext.RoleInfo.Where(t => 1 == 1).AsNoTracking().OrderBy(xy => xy.FatherId).ThenBy(x => x.Level);
            var pagedResultDto = new PagedResultDto<RoleInfoListDto>();
            pagedResultDto.TotalCount = await query.CountAsync();
            var userList = await query.Page(page, size).ToListAsync();
            var temList = ObjectMapper.Map<List<RoleInfo>, List<RoleInfoListDto>>(userList);

            if (groupid > 0)
            {
                foreach (var item in temList)
                {
                    item.IsEnable = false;
                }

                var binds = await _dbContext.GradeRole.Where(x => x.GradeId == groupid).AsNoTracking().ToListAsync();
                if (binds != null && binds.Count > 0)
                {
                    var roleids = binds.Select(x => x.RoleId).ToList();
                    var hitroles = temList.Where(x => roleids.Contains(x.Id)).ToList();
                    foreach (var item in hitroles)
                    {
                        item.IsEnable = true;
                    }
                }

            }
            pagedResultDto.Items = temList;

            return pagedResultDto;
        }

        /// <summary>
        /// 更新绑定
        /// </summary>
        /// <param name="groupid"></param>
        /// <param name="roleid"></param>
        /// <param name="state"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<int> UpdateBindRole(int groupid, int roleid, bool state)
        {
            var grade = _dbContext.GradeInfo.Where(x => x.Id == groupid).AsNoTracking().FirstOrDefault();

            var boolupdated = false;
            if (grade != null && grade != default)
            {
                if (state)
                {
                    var find = await _dbContext.GradeRole.Where(x => x.GradeId == groupid && x.RoleId == roleid).AsNoTracking().FirstOrDefaultAsync();
                    if (find == null || find == default)
                    {
                        boolupdated = true;
                        var one = new GradeRole();
                        one.GradeId = groupid;
                        one.RoleId = roleid;
                        _dbContext.Add(one);
                        await _dbContext.SaveChangesAsync();
                    }
                }
                else
                {
                    var find = await _dbContext.GradeRole.Where(x => x.GradeId == groupid && x.RoleId == roleid).FirstOrDefaultAsync();
                    if (find != null && find != default)
                    {
                        _dbContext.Remove(find);
                        await _dbContext.SaveChangesAsync();
                        boolupdated = true;
                    }
                }
            }
            if (boolupdated)
            {
                await _cache.DeleteAsync(string.Format(PublicString.CacheGradeInfoHead, grade.Name));
            }
            return 1;
        }

        /// <summary>
        /// 根据ID获取单项权限列表
        ///</summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public RoleInfoDto GetByIdAsync(int id)
        {
            var query = _dbContext.RoleInfo.Where(t => t.Id == id)
                .FirstOrDefault();
            var temList = ObjectMapper.Map<RoleInfo, RoleInfoDto>(query);
            return temList;
        }

        /// <summary>
        /// 根据ID获取待更新单项信息权限列表
        ///</summary>
        /// <param name="id"></param>
        /// <returns></returns>
        [HttpGet]
        public RoleInfoUpdateDto GetInfoForUpdateAsync(int id)
        {
            var query = _dbContext.RoleInfo.Where(t => t.Id == id)
                .FirstOrDefault();
            var temList = ObjectMapper.Map<RoleInfo, RoleInfoUpdateDto>(query);
            return temList;
        }

        
        /// <summary>
        /// 添加一个权限列表
        ///</summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<RoleInfoDto> CreateItemAsync(RoleInfoAddDto input)
        {
            //做排重处理
            var find = _dbContext.RoleInfo.Where(x => x.Model == input.Model && x.Role == input.Role).Any();
            if (find)
            {
                throw new $ext_safeprojectname$Exception("已经存在这样的权限，无法重复添加");
            }
            var info = ObjectMapper.Map<RoleInfoAddDto, RoleInfo>(input);
            info.IsEnable = true;//添加自定义
            _dbContext.Add(info);

            info.SortStr = info.Sort.ToString().PadLeft(_persize, '0') + "0".PadLeft((_maxlevel - 1) * _persize, '0');

            await _dbContext.SaveChangesAsync();
            if (input.FatherId != 0)
            {
                var father = _dbContext.RoleInfo.Where(x => x.Id == input.FatherId).AsNoTracking().FirstOrDefault();
                if (father != null && father != default)
                {
                    info.FatherStr = $"{father.FatherStr}{info.Id},";
                    info.Level = (father.Level + 1);
                    info.FatherId = father.Id;
                    info.RootId = father.RootId != 0 ? father.RootId : father.Id;
                    BuildSortStr(info, father);
                }
                else
                {
                    input.FatherId = 0;
                }
            }
            if (input.FatherId == 0)
            {
                info.FatherStr = $"{info.Id},";
                info.RootId = info.Id;
            }
            await _dbContext.SaveChangesAsync();
            var backinfo = ObjectMapper.Map<RoleInfo, RoleInfoDto>(info);
            return backinfo;
        }

        /// <summary>
        /// 更新一个权限列表
        ///</summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<RoleInfoDto> UpdateItemAsync(RoleInfoUpdateDto input)
        {
            var find = _dbContext.RoleInfo.Where(x => x.Id != input.Id && x.Model == input.Model && x.Role == input.Role).Select(x => x.Id).FirstOrDefault();
            if (find != 0)
            {
                throw new $ext_safeprojectname$Exception($"数据重复，权限的模块和权限值的组合不能重复！ {input.Model}-{input.Role}");
            }
            var info = await _dbContext.RoleInfo.Where(x => x.Id == input.Id).FirstOrDefaultAsync();
            if (info == null || info == default)
            {
                throw new $ext_safeprojectname$Exception("需要查询的信息不存在");
            }
            var old_father_str = info.FatherStr;
            var _chat_level = info.Level;
            ObjectMapper.Map<RoleInfoUpdateDto, RoleInfo>(input, info);
            if (info.FatherId != 0)
            {
                var father = _dbContext.RoleInfo.Where(x => x.Id == info.FatherId).AsNoTracking().FirstOrDefault();
                if (father != null && father != default)
                {
                    info.Level = father.Level + 1;
                    info.FatherStr = $"{father.FatherStr}{info.Id},";
                    info.RootId = father.RootId;
                    BuildSortStr(info, father);
                }
                else
                {
                    info.FatherId = 0;
                    info.FatherStr = $"{info.Id},";
                    info.Level = 0;
                    info.RootId = info.Id;
                    BuildSortStr(info,null);
                }
            }
            else
            {
                info.FatherId = 0;
                info.FatherStr = $"{info.Id},";
                info.Level = 0;
                info.RootId = info.Id;
                BuildSortStr(info, null);
            }
            _chat_level = _chat_level - (info.Level);
            if (old_father_str != info.FatherStr)
            {
                var suns = _dbContext.RoleInfo.Where(x => x.Id != info.Id && x.FatherStr.StartsWith(old_father_str)).ToList();
                if (suns != null && suns.Count > 0)
                {
                    foreach (var item in suns)
                    {
                        item.FatherStr = item.FatherStr.Replace(old_father_str, info.FatherStr);
                        item.Level = item.Level + _chat_level;
                        item.RootId = info.RootId;
                        BuildFootSortStr(item, info);
                    }
                }
            }
            var backinfo = ObjectMapper.Map<RoleInfo, RoleInfoDto>(info);
            await _dbContext.SaveChangesAsync();
            return backinfo;
        }

        /// <summary>
        /// 每层最大支持的排序位数 5表示00000
        /// </summary>
        private const int _persize = 5;
        /// <summary>
        /// 最大层级个数，从0开始 比如4就是 0 1 2 3
        /// </summary>
        private const int _maxlevel = 4;

        /// <summary>
        /// 基于父级和当前自己的排序信息，构建对应的排序字符串
        /// </summary>
        /// <param name="_info"></param>
        /// <param name="_father"></param>
        private void BuildSortStr(RoleInfo _info, RoleInfo _father)
        {
            if (_info.Level < _maxlevel)
            {
                if (_father == null)
                {
                    _info.SortStr = _info.Sort.ToString().PadLeft(_persize, '0') + "0".PadLeft(_persize * (_maxlevel - 1), '0');
                }
                else
                {
                    if (!string.IsNullOrEmpty(_father.SortStr))
                    {
                        _info.SortStr = _father.SortStr.Substring(0, (_father.Level + 1) * _persize) + _info.Sort.ToString().PadLeft(_persize, '0');
                        //补充尾巴
                        if (_info.Level < (_maxlevel - 1))
                        {
                            _info.SortStr += "0".PadLeft(_persize * (_maxlevel - 1 - _info.Level), '0');
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 上级或者祖籍变更的替换，自己之后的不变,中间层级也不变 
        /// </summary>
        /// <param name="_info"></param>
        /// <param name="_father">是自己的上级或者祖级</param>
        private void BuildFootSortStr(RoleInfo _info, RoleInfo _father)
        {
            var _old_sort_str = _info.SortStr;
            _info.SortStr = _father.SortStr.Substring(0, (_father.Level + 1) * _persize);
            _info.SortStr += _old_sort_str.Substring((_father.Level + 1) * _persize);
        }


    }
}
